
#ifndef SQLSelectParser_HEADER_H
#define SQLSelectParser_HEADER_H



#include "../ast/SQLExpr.h"
#include "../ast/SQLOrderBy.h"
#include "../ast/SQLSetQuantifier.h"
#include "../ast/expr/SQLIdentifierExpr.h"
#include "../ast/statement/SQLExprTableSource.h"
#include "../ast/statement/SQLJoinTableSource.h"

#include "../ast/statement/SQLSelect.h"
#include "../ast/statement/SQLSelectGroupByClause.h"
#include "../ast/statement/SQLSelectItem.h"
#include "../ast/statement/SQLSelectQuery.h"
#include "../ast/statement/SQLSelectQueryBlock.h"
#include "../ast/statement/SQLSubqueryTableSource.h"
#include "../ast/statement/SQLTableSource.h"
#include "../ast/statement/SQLUnionOperator.h"
#include "../ast/statement/SQLUnionQuery.h"
#include "../ast/statement/SQLWithSubqueryClause.h"
#include "../ast/statement/SQLWithSubqueryClause_Entry.h"

#include "SQLParser.h"
#include "SQLSelectListCache.h"
#include "../../utils/common_ptr.h"

class SQLExprParser;
// typedef boost::shared_ptr<SQLExprParser> SQLExprParser_ptr;
class SQLSelectParser : public SQLParser
{

	typedef SQLParser super;

private:
	// std::list<SQLSelectItem_ptr > selectList;
	//  protected:
public:
	SQLExprParser_ptr exprParser;
	SQLSelectListCache_ptr selectListCache;

	std::shared_ptr<SQLUnionQuery> createSQLUnionQuery();
	void withSubquery(SQLSelect_ptr select);
	void parseWhere(SQLSelectQueryBlock_ptr queryBlock);
	void parseGroupBy(SQLSelectQueryBlock_ptr queryBlock);
	SQLSelectItem_ptr parseSelectItem();
	virtual SQLTableSource_ptr parseTableSourceRest(SQLTableSource_ptr tableSource);
	SQLSelectQuery_ptr valuesQuery(BOOL_ptr acceptUnion);
	void parseWindow(SQLSelectQueryBlock_ptr queryBlock);
	void parseSortBy(SQLSelectQueryBlock_ptr queryBlock);
	void parseFetchClause(SQLSelectQueryBlock_ptr queryBlock);

public:
	SQLSelectParser(string_ptr sql);
	~SQLSelectParser();
	SQLSelectParser(Lexer_ptr lexer);
	SQLSelectParser(SQLExprParser_ptr exprParser);
	SQLSelectParser(SQLExprParser_ptr exprParser, SQLSelectListCache_ptr selectListCache);

	SQLSelect_ptr select();
	virtual std::shared_ptr<SQLUnionQuery> unionRest(std::shared_ptr<SQLUnionQuery> xunion);
	SQLSelectQuery_ptr queryRest(SQLSelectQuery_ptr selectQuery);
	SQLSelectQuery_ptr queryRest(SQLSelectQuery_ptr selectQuery, BOOL_ptr acceptUnion);
	SQLSelectQuery_ptr query();
	SQLSelectQuery_ptr query(SQLObject_ptr parent);
	virtual SQLSelectQuery_ptr query(SQLObject_ptr parent, BOOL_ptr acceptUnion);
	virtual void parseFrom(SQLSelectQueryBlock_ptr queryBlock);
	virtual SQLTableSource_ptr parseTableSource();
	SQLExpr_ptr expr();
	SQLOrderBy_ptr parseOrderBy();
	void acceptKeyword(string_ptr ident);
	void parseSelectList(SQLSelectQueryBlock_ptr queryBlock);
	void parseHierachical(SQLSelectQueryBlock_ptr queryBlock);

	void parseTableSourceQueryTableExpr(SQLExprTableSource_ptr tableReference);
	void parseTableSourceSample(SQLTableSource_ptr tableSource);
	void parsePivot(SQLTableSource_ptr tableSource);
	void parseTableSourceSampleHive(SQLTableSource_ptr tableSource);
	SQLTableSource_ptr primaryTableSourceRest(SQLTableSource_ptr tableSource);
	SQLValuesTableSource_ptr parseValues();
	SQLTableSource_ptr parseLateralView(SQLTableSource_ptr tableSource);
	void parseLateralViewAs(SQLLateralViewTableSource_ptr lateralViewTabSrc);
	SQLWithSubqueryClause_ptr parseWith();
};
// typedef boost::shared_ptr<SQLSelectParser> SQLSelectParser_ptr;

#endif
